﻿using PoemGame.Domain.GameAggregate;
using PoemGame.Domain.PlayerAggregate;
using PoemGame.Domain.Seedwork;
using PoemGame.Domain.Services;

namespace PoemGame.ApplicationService
{
    /// <summary>
    /// 封装游戏的过程，将回答顺序等在子类实现
    /// </summary>
    public abstract class GamePlayServiceBase : IGamePlayService
    {
        protected const int WINNER_SCORE = 10;
        protected const int ANSWER_CORRECT_SCORE = 1;
        protected readonly IGameRepository gameRepository;
        protected readonly IPlayerRepository playerRepository;
        protected readonly IDomainServiceFactory<ICheckAnswerService> checkAnswerServiceFactory;
 

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_gameRepository"></param>
        /// <param name="_playerRepository"></param>
        /// <param name="_checkAnswerServiceFactory"></param>
        /// <param name="_aftergameActionFactory"></param>
        public GamePlayServiceBase(
            IGameRepository _gameRepository,
            IPlayerRepository _playerRepository,
            IDomainServiceFactory<ICheckAnswerService> _checkAnswerServiceFactory
            )
        {

            gameRepository = _gameRepository;
            playerRepository = _playerRepository;
            checkAnswerServiceFactory = _checkAnswerServiceFactory;
        }
        /// <summary>
        /// 游戏进行
        /// </summary>
        /// <param name="player"></param>
        /// <param name="game"></param>
        /// <param name="answer"></param>
        /// <returns></returns>
        public async Task<GamePlayResult> GamePlay(Player player, Game game, string answer)
        {

            if (player == null) return new GamePlayResult { IsSuccess = false, Message = "玩家不存在", FaultReason = EnumGamePlayFaultReason.PlayerIsNull };
            if (game.Status == GameStatus.Done) return new GamePlayResult { IsSuccess = false, Message = "游戏已经结束", FaultReason = EnumGamePlayFaultReason.GameIsDone };
            if (game.Status == GameStatus.Ready) return new GamePlayResult { IsSuccess = false, Message = "游戏没有开始", FaultReason = EnumGamePlayFaultReason.GameNotStart };
            var playeringame = game.PlayersInGame.FirstOrDefault(o => o.PlayerId == player.Id);

            if (playeringame == null) return new GamePlayResult { IsSuccess = false, Message = "没有在游戏中", FaultReason = EnumGamePlayFaultReason.PlayerNotInGame };
            if (playeringame.PlayerStatus == PlayerGameStatus.Out) return new GamePlayResult { IsSuccess = false, Message = "已经出局", FaultReason = EnumGamePlayFaultReason.PlayerIsOut };

            GamePlayResult resbefore = CheckPlayerIsInturn(playeringame);
            if (!resbefore.IsSuccess) return resbefore;

            var res = new GamePlayResult
            {
                IsSuccess = true,
                FaultReason = EnumGamePlayFaultReason.None,
                IsGameDone = false
            };

            if (string.IsNullOrEmpty(answer))
            {
                answer = "";
            }

            bool IsProperAnswer = await game.Play(player, answer, checkAnswerServiceFactory); //CheckAnswer(game, answer);

            var message = "";
            if (IsProperAnswer)
            {
                playeringame.PlayerStatus = PlayerGameStatus.Waiting;
                message = player.UserName + "回答正确,";
                res.Message = message;
                res.IsAnswerCorrect = true;
            }
            else
            {
                playeringame.PlayerStatus = PlayerGameStatus.Out;
                message = player.UserName + "出局,";
                res.Message = message;
                res.IsAnswerCorrect = false;
            }

            await AfterPlayerAnswer(player, IsProperAnswer);

            var activateplayers = game.GetWaitingPlayers();
            if (activateplayers.Count == 1 && IsProperAnswer)
            {
                var activateplayer = await playerRepository.GetPlayerByIdAsync(activateplayers[0].PlayerId);
                message += $"游戏结束,{activateplayer.UserName}获胜";
                await PlayerWin(activateplayer);
                game.GameOver(activateplayer);
                res.Message = message;
                res.IsGameDone = true;
            }
            else if (activateplayers.Count == 0)
            {
                //游戏结束，没有赢家
                message += $"游戏结束,没有赢家";
                game.GameOver();
                res.Message = message;
                res.IsGameDone = true;
            }
            else
            {
                string mess = await SetNextPlayer(player, game);
                if (!string.IsNullOrEmpty(mess)) message += mess;
                res.Message = message;
            }
            await gameRepository.UpdateAsync(game);
            return res;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="activateplayer"></param>
        /// <returns></returns>
        protected virtual async Task PlayerWin(Player activateplayer)
        {
            activateplayer.IncreaseScore(WINNER_SCORE);//获胜加十分
            await playerRepository.UpdateAsync(activateplayer);
        }
        /// <summary>
        /// 设置下一个作答的玩家
        /// </summary>
        /// <param name="player"></param>
        /// <param name="game"></param>
        /// <returns></returns>
        protected abstract Task<string> SetNextPlayer(Player player, Game game);
        /// <summary>
        /// 
        /// </summary>
        /// <param name="playeringame"></param>
        /// <returns></returns>
        protected GamePlayResult CheckPlayerIsInturn(PlayerInGame playeringame)
        {
            if (playeringame.PlayerStatus == PlayerGameStatus.Waiting)
                return new GamePlayResult { IsSuccess = false, Message = "没有轮到", FaultReason = EnumGamePlayFaultReason.PlayerNotInturn };
            return new GamePlayResult { IsSuccess = true, Message = "", FaultReason = EnumGamePlayFaultReason.None };
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="player"></param>
        /// <param name="isAnswerProper"></param>
        /// <returns></returns>
        protected virtual async Task AfterPlayerAnswer(Player player, bool isAnswerProper)
        {
            if (isAnswerProper)
            {
                player.IncreaseScore(ANSWER_CORRECT_SCORE);//回答正确加一分
                await playerRepository.UpdateAsync(player);
            }
        }

        public abstract Task<GeneralResult> SetPlayer(Player player, Game game);
    }
}
